package com.pengzy.auth.services;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.pengzy.auth.dto.LoginBo;
import com.pengzy.comment.core.enums.PrErrorEnum;
import com.pengzy.comment.core.enums.SecurityEnum;
import com.pengzy.comment.core.jwt.JwtUtil;
import com.pengzy.comment.mybatis.entity.SysUser;
import com.pengzy.comment.mybatis.mapper.SysUserMapper;
import com.pengzy.comment.web.exception.CustomException;
import com.pengzy.comment.web.redis.RedisCache;
import com.pengzy.comment.web.result.JsonResult;
import com.pengzy.comment.web.result.ServletUtils;
import com.pengzy.comment.web.webFluxUtils.webFluxUtil;
import com.pengzy.supports.dto.LoginResult;
import com.pengzy.supports.dto.LoginUser;
import com.pengzy.supports.dto.LoginUserDetails;
import com.pengzy.supports.service.SysUserService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.ServletRequestAttributes;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author xiaozhi 2023/7/7
 */

@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;
    //@Autowired
    //private ReactiveAuthenticationManager reactiveAuthenticationManager;
    @Resource
    private RedisCache redisCache;
    @Resource
    private SysUserService sysUserService;

    @SneakyThrows
    @Override
    public JsonResult<LoginUser> login(LoginBo bo) {
        log.info("登录中..........");
        long start=System.currentTimeMillis();
        UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(bo.getUser(),bo.getPass());
        Authentication authentication=  authenticationManager.authenticate(authenticationToken);

        if(Objects.isNull(authentication)){
            throw new CustomException(PrErrorEnum.ERROR_1001.getInfo(),PrErrorEnum.ERROR_1001.getCode());
        }
        LoginUser loginUser =(LoginUser)(authentication.getPrincipal());
        String userId =loginUser.getUser().getUserId().toString();
        String jwt = JwtUtil.createJWT(userId);
        loginUser.setToken(jwt);
        //authenticate存入redis 时效一天
        redisCache.setCacheObject(SecurityEnum.LOGIN_KEY.getValue()+userId,loginUser,24, TimeUnit.HOURS);
        loginUser.setUser(null);
        loginUser.setPassword(null);
        log.info(String.valueOf(System.currentTimeMillis()-start));
//        //把token响应给前端
        return JsonResult.success("登录成功", loginUser);
    }



    @SneakyThrows
    @Override
    public JsonResult<String> logout(LoginBo bo) {
        SysUser one = sysUserService.lambdaQuery()
                .eq(SysUser::getUserName, bo.getUser())
                .one();
        if(one==null){
            throw new CustomException(PrErrorEnum.ERROR_1005.getInfo(),PrErrorEnum.ERROR_1005.getCode());
        }
        //清除security上下文
        SecurityContextHolder.clearContext();
        redisCache.expire(SecurityEnum.LOGIN_KEY.getValue()+one.getUserId(),1, TimeUnit.SECONDS);
        return JsonResult.success("退出成功");
    }
}
